module dogre.framelistener;

extern(C)
{
    void* getFrameListenerWrapper(flfunc ptrToF_S, flfunc ptrToF_E, flfunc ptrToF_RQ);
    struct FrameEvent
    {
        float timeSinceLastEvent;
        float timeSinceLastFrame;
    }
}

alias bool function(void* ptrToWrapper, ref const(FrameEvent) evt) flfunc;


//Generate functions that are called by the C++ for handler classes
string GenListenerHandler(string htype)
{
    return  `__gshared FrameListener[void*] allFrame`~htype~`edListeners;
             extern(C) bool callFrame`~htype~`edHandle(void* ptrToWrapper, ref const(FrameEvent) evt)
             {
                 if(ptrToWrapper in allFrame`~htype~`edListeners)
                 {
                     return allFrame`~htype~`edListeners[ptrToWrapper].frame`~htype~`ed(evt);
                 }
                 return true;
             }`;
}

mixin(GenListenerHandler("Start"));
mixin(GenListenerHandler("End"));
mixin(GenListenerHandler("RenderingQueu"));

class FrameListener
{
    public void* ptrToWrapper;
    
    final this()
    {
        ptrToWrapper = getFrameListenerWrapper(&callFrameStartedHandle, &callFrameEndedHandle, &callFrameRenderingQueuedHandle);
        allFrameStartedListeners[ptrToWrapper] = this;
        allFrameEndedListeners[ptrToWrapper] = this;
        allFrameRenderingQueuedListeners[ptrToWrapper] = this;
    }

    final ~this()
    {
        allFrameStartedListeners.remove(ptrToWrapper);
        allFrameEndedListeners.remove(ptrToWrapper);
        allFrameRenderingQueuedListeners.remove(ptrToWrapper);
    }
    bool frameStarted(ref const(FrameEvent) evt)
    {
        return true;
    }
    bool frameEnded(ref const(FrameEvent) evt)
    {
        return true;
    }
    bool frameRenderingQueued(ref const(FrameEvent) evt)
    {
        return true;
    }
}
